/*
 *  * Copyright (c) 2016. For Intelligent Group.
 */

package com.intelligent.ispc.utils;

import com.google.common.collect.Lists;
import com.intelligent.ispc.common.mapper.JsonMapper;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.utils.ResourceBundleUtils;
import com.intelligent.ispc.constant.AppConstant;
import com.intelligent.ispc.foundation.io.ProcessStreamHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by julia on 16/8/25.
 * Updated by Can Guan on 16/9/20
 */
public class PythonUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(PythonUtil.class);

    /*
        temp result for Spc ColumnKeys
     */
    private static Map<String, List<String>> spcColumnkeys = new LinkedHashMap<>();

    /*
        Util for Json conversion
     */
    private JsonMapper jsonMapper = JsonMapper.nonDefaultMapper();

    /*
        id for parent process
     */
    private String parentId;

    /**
     * constructor
     *
     * @param parentId id for parent process
     */
    public PythonUtil(String parentId) {
        this.parentId = parentId;
    }

    /**
     * empty constructor
     */
    public PythonUtil() {
        this.parentId = null;
    }

    /*
        private method to initialize argument with path of specified python script
     */
    private List<String> getArgument(String scriptPath) {
        List<String> argument = Lists.newLinkedList();
        String filePath = scriptPath.substring(0, scriptPath.lastIndexOf("/"));
        String fileName = scriptPath.substring(scriptPath.lastIndexOf("/") + 1, scriptPath.lastIndexOf("."));
        argument.add(filePath);
        argument.add(fileName);
        return argument;
    }

    /*
        private method to initialize argument without script path
     */
    private List<String> getArgument() {
        return getArgument(ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME));
    }

    /**
     * get all data information from csv file
     * @param filePaths paths of csv files
     * @return return all data information
     */
    @Deprecated
    public Map<String, Object> getDatas(List<String> filePaths) {
        Map<String, Object> mapResult = new LinkedHashMap<>();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument();
                    args.add(filePaths.get(i));
                    args.add("print_all_data");
                    List<String> result = exec(args);

                    final int num0 = 0, num1 = 1, num2 = 2, num3 = 3, num4 = 4;
                    //PID
                    String pid = result.get(num0);
                    //DATA_PARAM
                    String param = result.get(num1);
                    //DATA_INFO
                    String data = result.get(num2);
                    //DATA_SEARCH_KEYS
                    String searchKey = result.get(num3);
                    //DATA_ATTRIBUTE_KEYS
                    String attributeKey = result.get(num4);

                    mapResult.put(AppConstant.DATA_PARAM + i, param);
                    mapResult.put(AppConstant.DATA_INFO + i, data);
                    mapResult.put(AppConstant.DATA_SEARCH_KEYS + i, searchKey);
                    mapResult.put(AppConstant.DATA_ATTRIBUTE_KEYS + i, attributeKey);
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        return mapResult;
    }

    /**
     * get data information from csv files
     * @param filePaths paths of csv files
     * @param scriptPath specified file path of python script
     * @return return data information of csv file
     */
    @Deprecated
    public Map<String, Object> getDatas(List<String> filePaths, String scriptPath) {
        Map<String, Object> mapResult = new LinkedHashMap<>();

        try {
            for (String filePath : filePaths) {
                File file = new File(filePath);
                if (!file.isFile()) {
                    throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
                }
            }

            File script = new File(scriptPath);
            if (!script.isFile()) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            }

            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_all_data");
                    List<String> result = exec(args);

                    final int num0 = 0, num1 = 1, num2 = 2, num3 = 3, num4 = 4;
                    //PID
                    String pid = result.get(num0);
                    //DATA_PARAM
                    String param = result.get(num1);
                    //DATA_INFO
                    String data = result.get(num2);
                    //DATA_SEARCH_KEYS
                    String searchKey = result.get(num3);
                    //DATA_ATTRIBUTE_KEYS
                    String attributeKey = result.get(num4);

                    mapResult.put(AppConstant.DATA_PARAM + i, param);
                    mapResult.put(AppConstant.DATA_INFO + i, data);
                    mapResult.put(AppConstant.DATA_SEARCH_KEYS + i, searchKey);
                    mapResult.put(AppConstant.DATA_ATTRIBUTE_KEYS + i, attributeKey);
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        return mapResult;
    }

    /**
     * get search keys
     *
     * @param filePaths paths of csv files
     * @return list of search keys, order by filePaths
     */
    public List<String> getSearchKeys(List<String> filePaths) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getSearchKeys(filePaths, scriptPath);
    }

    /**
     * get search keys
     *
     * @param filePaths  paths of csv files
     * @param scriptPath path of specified python script
     * @return list of search keys, order by filePaths
     */
    public List<String> getSearchKeys(List<String> filePaths, String scriptPath) {
        LOGGER.debug("Python get searchKeys start");
        List<String> resultList = Lists.newLinkedList();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_search_keys");
                    List<String> result = exec(args);
                    String searchKey = result.get(1);
                    resultList.add(searchKey);
                    searchKey = null;
                    result = null;
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        LOGGER.debug("Python get searchKeys end");
        return resultList;
    }

    /**
     * get attribute keys
     *
     * @param filePaths paths of csv file
     * @return list of attribute keys, order by filePaths
     */
    public List<String> getAttributeKeys(List<String> filePaths) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getAttributeKeys(filePaths, scriptPath);
    }

    /**
     * get attribute keys
     *
     * @param filePaths  paths of csv files
     * @param scriptPath path of specified python script
     * @return list of attribute keys, order by filePaths
     */
    public List<String> getAttributeKeys(List<String> filePaths, String scriptPath) {
        LOGGER.debug("Python get attributeKeys start");
        List<String> resultList = Lists.newLinkedList();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_attribute_keys");
                    List<String> result = exec(args);
                    String attributeKey = result.get(1);
                    resultList.add(attributeKey);
                    attributeKey = null;
                    result = null;
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        LOGGER.debug("Python get attributeKeys end");
        return resultList;
    }

    /**
     * get param keys
     *
     * @param filePaths paths of csv files
     * @return list of param keys, order by filePaths
     */
    public List<String> getParamKeys(List<String> filePaths) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getParamKeys(filePaths, scriptPath);
    }


    /**
     * get param keys
     *
     * @param filePaths  paths of csv files
     * @param scriptPath path of specified python path
     * @return list of param keys, order by filePath
     */
    public List<String> getParamKeys(List<String> filePaths, String scriptPath) {
        LOGGER.debug("Python get usl and lsl start");
        List<String> resultList = Lists.newLinkedList();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_param_keys");
                    List<String> result = exec(args);
                    String param = result.get(1);
                    resultList.add(param);
                    result = null;
                    param = null;
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        LOGGER.debug("Python get usl and lsl end");
        return resultList;
    }

    /**
     * get column names from csv file, excluding search keys, attribute keys and invalid column name
     *
     * @param filePaths paths of csv files
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getColumnKeys(filePaths, scriptPath);
    }

    /**
     * get column names from csv files, excluding search keys and attribute keys
     *
     * @param filePaths paths of csv files
     * @param flag      flag for excluding invalid column names or not
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths, Boolean flag) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getColumnKeys(filePaths, scriptPath, flag);
    }

    /**
     * get column names from csv files, excluding search keys and attribute keys
     *
     * @param filePaths  paths of csv files
     * @param scriptPath path of specified python script
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths, String scriptPath) {
        return getColumnKeys(filePaths, scriptPath, true, null);
    }

    /**
     * get column names from csv files, excluding search keys and attribute keys
     *
     * @param filePaths  paths of csv files
     * @param scriptPath path of specified python script
     * @param flag       flag for excluding invalid column names or not
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths, String scriptPath, Boolean flag) {
        return getColumnKeys(filePaths, scriptPath, flag, null);
    }

    /**
     * get column names from csv files, excluding search keys, attribute keys and invalid column names
     *
     * @param filePaths    paths of csv files
     * @param scriptPath   path of specified python script
     * @param includeValue Exceptional value in invalid value
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths, String scriptPath, List<String> includeValue) {
        return getColumnKeys(filePaths, scriptPath, true, null);
    }

    /**
     * get column names from csv files, excluding search keys, attribute keys
     *
     * @param filePaths    paths of csv files
     * @param scriptPath   path of specified python script
     * @param flag         flag of excluding invalid column name or not
     * @param includeValue Exceptional value in invalid value
     * @return list of column names, order by filePaths
     */
    public List<String> getColumnKeys(List<String> filePaths, String scriptPath, Boolean flag, List<String> includeValue) {
        LOGGER.debug("Python get column names start");
        List<String> resultList = Lists.newLinkedList();
        try {
            if ("spc".equals(parentId)) {
                spcColumnkeys.clear();
            }
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_column_names");
                    if (flag) {
                        args.add("True");
                    }
                    if ((includeValue != null) && (includeValue.size() != 0)) {
                        for (String str : includeValue) {
                            args.add(str);
                        }
                    }
                    List<String> result = exec(args);
                    String columnNames = result.get(1);
                    resultList.add(columnNames);
                    if ("spc".equals(parentId)) {
                        File file = new File(filePaths.get(i));
                        spcColumnkeys.put(file.getPath(), jsonMapper.fromJson(columnNames, List.class));
                    }
                    columnNames = null;
                    result = null;
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        LOGGER.debug("Python get column names end");
        return resultList;
    }

    /**
     * get data of specified column names from csv files, including search keys value and attribute keys value
     *
     * @param filePaths   paths of csv files
     * @param columnNames list of specified column names
     * @return data map from csv file, Key correspond to order of filePaths, Value is data of each record
     */
    public Map<String, List<String>> getDataByName(List<String> filePaths, List<String> columnNames) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getDataByName(filePaths, columnNames, scriptPath);
    }

    /**
     * get data of specified column names from csv files, including search keys value and attribute keys value
     *
     * @param filePaths   paths of csv files
     * @param columnNames list of specified column names
     * @param scriptPath  path of specified python script
     * @return data map from csv file, Key correspond to order filePaths, Value is data of each record
     */
    public Map<String, List<String>> getDataByName(List<String> filePaths, List<String> columnNames, String scriptPath) {
        LOGGER.debug("Python get data start");
        Map<String, List<String>> resultMap = new LinkedHashMap<>();
        if (!"spc".equals(parentId)) {
            try {
                if (filePaths != null && !filePaths.isEmpty()) {
                    for (int i = 0; i < filePaths.size(); i++) {
                        List<String> args = getArgument(scriptPath);
                        args.add(filePaths.get(i));
                        args.add("print_data_by_names");
                        if ((columnNames != null) && (columnNames.size() != 0)) {
                            for (String str : columnNames) {
                                args.add(str);
                            }
                        }
                        List<String> result = exec(args);
                        resultMap.put(AppConstant.DATA_INFO + i, result.subList(1, result.size()));
                        result = null;
                    }
                }
            } catch (Exception e) {
                if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                    throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
                }
            }
        } else {
            try {
                if (filePaths != null && !filePaths.isEmpty()) {
                    for (int i = 0; i < filePaths.size(); i++) {
                        List<String> args = getArgument(scriptPath);
                        args.add(filePaths.get(i));
                        args.add("print_data_by_names");
                        if ((columnNames != null) && (columnNames.size() != 0)) {
                            for (String str : columnNames) {
                                File file = new File(filePaths.get(i));
                                if (spcColumnkeys.get(file.getPath()).contains(str)) {
                                    args.add(str);
                                }
                            }
                        }
                        final int num5 = 5;
                        if (args.size() < num5) {
                            continue;
                        }
                        List<String> result = exec(args);
                        resultMap.put(AppConstant.DATA_INFO + i, result.subList(1, result.size()));
                        result = null;
                    }
                }
            } catch (Exception e) {
                if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                    throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
                } else {
                    throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
                }
            }
        }
        LOGGER.debug("Python get data end");
        return resultMap;
    }

    /**
     * get data of specified column names in temp file from csv files, including search keys value and attribute keys value
     *
     * @param filePaths  paths of csv files
     * @param targetFile path of tempt file
     * @return data map from csv file, Key correspond to order filePaths, Value is data of each record
     */
    public Map<String, List<String>> getDataByFile(List<String> filePaths, String targetFile) {
        String scriptPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_SCRIPT_FILENAME);
        return getDataByFile(filePaths, targetFile, scriptPath);
    }

    /**
     * get data of specified column names in temp file from csv files, including search keys value and attribute keys value
     *
     * @param filePaths  paths of csv files
     * @param scriptPath paths of specified python script
     * @param targetFile path of tempt file
     * @return data map from csv file, Key correspond to order filePaths, Value is data of each record
     */
    public Map<String, List<String>> getDataByFile(List<String> filePaths, String scriptPath, String targetFile) {
        Map<String, List<String>> resultMap = new LinkedHashMap<>();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_data_by_file");
                    args.add(targetFile);
                    List<String> result = exec(args);
                    resultMap.put(AppConstant.DATA_INFO + i, result.subList(1, result.size()));
                    result = null;
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        return resultMap;
    }

    /**
     * get data from csv file for python script test
     *
     * @param filePaths  paths of csv file
     * @param scriptPath path of specified csv files
     * @param rowNum     Number of rows to show in script test
     * @param columnNum  Number of columns to show in script test
     * @return list of data
     */
    public List<String> getDataForScriptTest(List<String> filePaths, String scriptPath, int rowNum, int columnNum) {
        List<String> result = Lists.newLinkedList();
        try {
            if (filePaths != null && !filePaths.isEmpty()) {
                for (int i = 0; i < filePaths.size(); i++) {
                    List<String> args = getArgument(scriptPath);
                    args.add(filePaths.get(i));
                    args.add("print_data_for_script_test");
                    args.add(String.valueOf(rowNum));
                    args.add(String.valueOf(columnNum));
                    result = exec(args);
                }
            }
        } catch (Exception e) {
            if (e.getMessage().equals(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST)) {
                throw new ApplicationException(ExceptionMessages.ERR_15004, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PATH_DOESNOT_EXIST));
            } else {
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
        }
        return result;
    }

    /*
        private method to execute python argument and return the data from csv file
     */
    private List<String> exec(List<String> arg) {
        List<String> result = Lists.newLinkedList();
        List<String> errorList = Lists.newLinkedList();
        try {
            String importPath = ApplicationPathUtil.getPath(AppConstant.PATH_SCRIPT, AppConstant.PATH_IMPORT_SCRIPT_FILENAME);
            arg.add(0, importPath);
            arg.add(0, "python");
            final String[] args = arg.toArray(new String[0]);
            Process p = Runtime.getRuntime().exec(args);
            ProcessStreamHelper errorGobbler = new ProcessStreamHelper(p.getErrorStream(), ProcessStreamHelper.ERROR,
                    new ProcessStreamHelper.ProcessCallBack() {
                        @Override
                        public void readAll(List<String> arg) {
                            errorList.addAll(arg);
                        }
                    });
            ProcessStreamHelper outputGobbler = new ProcessStreamHelper(p.getInputStream(), ProcessStreamHelper.OUTPUT,
                    new ProcessStreamHelper.ProcessCallBack() {
                        @Override
                        public void readAll(List<String> arg) {
                            result.addAll(arg);
                        }
                    });

            errorGobbler.start();
            outputGobbler.start();
            p.waitFor();
            final int num300 = 300, num100 = 100;
            if (result.isEmpty()) {
                Thread.sleep(num300);
            } else {
                Thread.sleep(num100);
            }
            if (errorList.size() > 0) {
                LOGGER.error("Argument : ", String.join(" ", (String[]) arg.toArray(new String[0])));
                LOGGER.error(String.join("\n", (String[]) errorList.toArray(new String[0])));
                throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
            }
            return result;
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            LOGGER.error("Argument : ", String.join(" ", (String[]) arg.toArray(new String[0])));
            throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
            LOGGER.error("Argument : ", String.join(" ", (String[]) arg.toArray(new String[0])));
            throw new ApplicationException(ExceptionMessages.ERR_15003, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_PYTHON_SCRIPT_ERROR));
        }
    }
}
